//7-3. 状态常量，为代码方便理解和后期维护，我们一般状态定义为外部常量
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功，执行 resolve 后的状态，then 里面会执行 resolveCallBack 函数
const REJECTED = 'rejected'; // 失败，执行 reject 后的状态，then 里面会执行 rejectCallBack 函数

class MyPromise{
    //1.首先得有个构造函数
    //从 new promise((resolve,reject)=>{})，可以看出，constructor 需要传入一个function，
    // 该function包含两个参数： resolve 和 reject
    constructor (fn) {
        //3-1. new promise((resolve,reject)=>{
        //     resolve()
        // }).then()
        // 我们一般在 new Promise 前并不需要提前定义 resolve() 方法，但是却可以在 new 之后立马调用这个方法，
        // 由此看出 new 的时候实现了将 Promise 内部的一个已定义好的内部方法通过 new 操作绑定给 ① resolve ; 
        // 怎么实现绑定？那就是在 constructor 里面立马运行传进来的这个方法，且把 内部定义的 某两个方法分别传给 resolve 和 reject
        fn(this.resolve, this.reject);
    }
    //7-2. 定义此标识命名为 status，至少应有三个状态，①需运行 resolve 时状态，②需运行 reject 时状态，③ resolve、reject 都不运行时状态
    status = PENDING;
    //8-1. 保存的 resolve 传入 value 值的变量
    value = undefined;
    //8-1. 保存的 reject 传入 reason 值的变量
    reason = undefined;
    resolveCallBack = undefined;
    rejectCallBack = undefined;
    //2. new promise((resolve,reject)=>{}).then() 可以看出，promise 应该包含一个 then() 方法
    then(resolveCallBack, rejectCallBack){ 
        //7-1. 从 Promise().then(function(){}, function(){}) 看出 then 方法有两个函数参数，而且这两个方法，具体会执行哪一个是要根据定义时，运行的是 resolve 方法还是 reject 方法，
        // 如果定义时运行的是 resolve ,则在 then 这边将运行传入的第一个函数， 如果定义时运行的 reject 方法，则在 then 这边将运行传入的第二个函数，故此我们可以将传入的函数命名为
        // resolveCallBack 和 rejectCallBack ，同样的，我们也需要在 then 、resolve 、reject 方法之外公共部分定义一个状态，来标识定义时运行了哪个方法，
        // 并以此标识来判断运行 then 时该执行第一个还是第二个方法，
        //8. 从 Promise().then().then() 看出，then 方法返回的也是一个 Promise 对象;
        // 有时 then 方法只会传入 resolveCallBack 方法，故需配置参数可选
        resolveCallBack = resolveCallBack ? resolveCallBack : value => value;
        rejectCallBack = rejectCallBack ? rejectCallBack: reason => { throw reason };
        //10. then 方法的链式调用需要满足 then 方法返回的是一个 promise 对象
        let myPromise = new myPromise((resolve, reject) => {
            //7-5. 先判断状态
            if(this.status === FULFILLED){
                //10-2. 传入上次 then 的结果，给下一个 then 的调用对象
                let x = resolveCallBack( this.value );
                resolve( x );
            }else if(this.status === REJECTED){
                //10-2. 传入上次 then 的结果，给下一个 then 的调用对象
                let x = rejectCallBack( this.reason );
                reject( x );
            }else{
                //9. 定义时运行的 resolve 或 reject 方法里面包含异步（没有立即执行时）操作时，状态会延迟改变
                //则 resolve / reject 方法会延迟执行，延迟执行时则就不可以根据状态来判断应该执行哪个 callback 了
                //但是可以根据延迟后具体执行的 resolve / reject 来触发执行相应的 callback ,届时触发时我们需要保证 callback 方法还能正常调用到
                //故此，我们需将对应的 callback 函数保存起来
                this.resolveCallBack = resolveCallBack;
                this.rejectCallBack = rejectCallBack;
            }
        });
        //10-1. 返回 promise 对象，此 promise 对象, 执行 resolve、reject 时，应该传入上次 then 的结果
        return myPromise;
    }
    //3-2. 同时定义一个 resolve() 方法，该方法可以传入参数
    resolve(value) {
        //7-4. 定义时只能选择运行 resolve 或 reject 方法其中的一个，哪怕写了多个最终运行完头一个后后续的也将不再运行
        if(this.status !== PENDING) return;
        //7-3-1. 改变状态 
        this.status = FULFILLED;
        //8-1. resolve 方法传入的参数，是需要传给 then 里面的 resolveCallBack 方法作为参数的，故 value 需要保存起来
        this.value = value;
        //9-1. resolveCallBack 函数存在，则说明走到了 then 方法里的延迟执行 else 情况里，故需触发 callback
        this.resolveCallBack && this.resolveCallBack(this.value)
    }
    //3-3. 同时定义一个 reject() 方法，该方法可以传入参数
    reject(reason) {
        //7-4. 定义时只能选择运行 resolve 或 reject 方法其中的一个，哪怕写了多个最终运行完头一个后后续的也将不再运行
        if(this.status !== PENDING) return;
        //7-3-2. 改变状态
        this.status = REJECTED;
        //8-1. reject 方法传入的参数，是需要传给 then 里面的 rejectCallBack 方法作为参数的，故 reason 需要保存起来
        this.reason = reason;
        //9-2. resolveCallBack 函数存在，则说明走到了 then 方法里的延迟执行 else 情况里，故需触发 callback
        this.rejectCallBack && this.rejectCallBack(this.reason)
    }
    //4. 支持 Promise.resolve 故，应有一个 static 的 resolve() 方法
    static resolve(){

    }
    //5. 支持 Promise.all 故，应有一个 static 的 all() 方法
    static all(){

    }
    //6. 从 Promise().then().then() 看出，then 方法返回的也是一个 Promise 对象;
    // Promise().then().catch() 看出，promise 对象内部应该有一个 catch() 方法
    catch(){

    }
}